import axios from "axios";
import router from "@/router";
import Qs from "qs";
import type {AxiosResponse, InternalAxiosRequestConfig, AxiosInstance} from 'axios'
import {ElLoading, ElMessage, ElNotification, ElMessageBox} from 'element-plus'
import {useCounterStore} from "@/store/counter";
import {blobValidate, tansParams} from "@/utils";
import {getToken} from "@/utils/auth";
import {saveAs} from 'file-saver'
import {signString} from "@/utils/authentication";


const modeMap: Record<string, string> = {
    'base': import.meta.env.VITE_API_BASEPATH,
    'development': import.meta.env.VITE_APP_BASE_URL,
    'production': import.meta.env.VITE_APP_BASE_URL,
}
let BASE_URL
if (modeMap[import.meta.env.MODE]) {
    BASE_URL = modeMap[import.meta.env.MODE]
}
const useRequest: AxiosInstance = axios.create({
    baseURL: BASE_URL,
    timeout: 10000
})

const errorCode: Record<string, string> = {
    '40001': '请求参数缺失，客户端需检查请求参数是否与接口文档一致',
    '40002': '请求头缺少用户token',
    '404': '访问资源不存在',
    'default': '系统未知错误，请反馈给管理员'
}
// @ts-ignore
useRequest.interceptors.request.use((request: InternalAxiosRequestConfig) => {
    request.headers = {
        ...signString({
            method: request.method as string,
            path: request.url as string,
            data: request.method == 'get' ? request.params : request.data
        }),
        ...{token: getToken() as string}
    }  as any
    return request
}, error => {
    Promise.reject(error)
})

// @ts-ignore
useRequest.interceptors.response.use((res: AxiosResponse) => {
        const code = res.data.code || 0;
        const msg = errorCode[code] || res.data.msg || errorCode['default']
        if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
            return res.data
        }
        if (code == 40003) {
            ElMessage({message: '登录状态已过期，请重新登录。', type: 'warning'})
            ElMessageBox.confirm('登录状态已过期，您可以继续留在该页面，或者重新登录', '系统提示', {
                confirmButtonText: '重新登录',
                cancelButtonText: '取消',
                closeOnClickModal: false,
                type: 'warning'
            }).then(() => {
                const store: any = useCounterStore()
                store.logOut().then(() => {
                    router.go(0);
                })
            }).catch(() => {
            })
            return Promise.reject('无效的会话，或者会话已过期，请重新登录。')
        } else if (code === 500) {
            ElMessage({message: msg, type: 'error'})
            return Promise.reject(new Error(msg))
        } else if (code === 601) {
            ElMessage({message: msg, type: 'warning'})
            return Promise.reject(new Error(msg))
        } else if (code !== 0) {
            ElNotification.error({title: msg})
            return Promise.reject('error')
        } else {
            return Promise.resolve(res.data)
        }

    },
    error => {
        let {message} = error;
        if (message == "Network Error") {
            message = "后端接口连接异常";
        } else if (message.includes("timeout")) {
            message = "系统接口请求超时";
        } else if (message.includes("Request failed with status code")) {
            message = "系统接口" + message.substr(message.length - 3) + "异常";
        }
        ElMessage({message: message, type: 'error', duration: 5 * 1000})
        return Promise.reject(error)
    })

class baseRequest {
    qspost(url: string, data: mapType = {}): Promise<AxiosResponse<any, any>> {
        return new Promise((resolve, reject): void => {
            useRequest.post(url, Qs.stringify(data)).then(res => {
                resolve(res)
            }).catch((): void => {
            })
        })
    }

    post(url: string, data: mapType = {}): Promise<AxiosResponse<any, any>> {
        return new Promise((resolve, reject): void => {
            useRequest.post(url, data).then(res => {
                resolve(res)
            }).catch((): void => {
            })
        })
    }

    get(url: string, params: mapType = {}): Promise<AxiosResponse<any, any>> {
        return new Promise((resolve, reject): void => {
            useRequest.get(url, {params}).then(res => {
                resolve(res)
            }).catch((): void => {
            })
        })
    }

    put(url: string, params: mapType = {}): Promise<AxiosResponse<any, any>> {
        return new Promise((resolve, reject): void => {
            useRequest.put(url, params).then(res => {
                resolve(res)
            }).catch((): void => {
            })
        })
    }

    delete(url: string, params: mapType = {}): Promise<AxiosResponse<any, any>> {
        return new Promise((resolve, reject): void => {
            useRequest.delete(url, {params}).then(res => {
                resolve(res)
            }).catch((): void => {
            })
        })
    }

    exportFile(url: string, params: Record<string, any>, filename: string, config?: Record<string, any>): Promise<any> {
        let downloadLoadingInstance: { close: () => void; };
        downloadLoadingInstance = ElLoading.service({text: "正在导出文件，请稍候", background: "rgba(0, 0, 0, 0.7)",})
        return useRequest.post(url, params, {
            transformRequest: [(params: any) => {
                return tansParams(params)
            }],
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            responseType: 'blob',
            ...config
        }).then(async (data: any): Promise<void> => {
            const isBlob: boolean = blobValidate(data);
            if (isBlob) {
                const blob: Blob = new Blob([data])
                saveAs(blob, filename)
            } else {
                const resText = await data.text();
                const rspObj = JSON.parse(resText);
                const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
                ElMessage.error(errMsg);
            }
            downloadLoadingInstance.close();
        }).catch((): void => {
            ElMessage.error('导出文件失败！')
            downloadLoadingInstance.close();
        })
    }
}

export default new baseRequest()
